A glyph is an image used to visually represent a character or characters. For example, a font may be a set of glyphs where each character of the font represents a single glyph. However, a glyph may also include multiple characters of a font and vice versa. That is, one character of a font may correspond to several glyphs or several characters of a font to one glyph. In other words, a glyph is the shape of a series of curves that delimit the area used to represent a character or characters. The computer-implemented process used to generate glyph curves and the resulting characters is referred to as text rendering.
Rendering text can be one of the more expensive operations in terms of central processing unit (CPU) usage. One process for rendering text includes the four step process of rasterizing, merging, filtering, and blending. The rasterizing step includes converting the glyph curves to a bitmap. The format of the bitmap is typically 1-bit-per-pixel and it may be “overscaled” in one or more directions. For example, the bitmap may be overscaled in the vertical or horizontal direction. Overscaling refers to a process where each bit of data, or texel, used to generate the bitmap is smaller than the pixel used to display the glyph.
The merging step includes merging nearby glyphs to prevent artifacts or undesirable characters. For example, anti-aliasing (including sub-pixel rendering) involves drawing some pixels semi-transparently. Because each glyph may be drawn independently, it is possible for the same pixel to be drawn semi-transparently multiple times in locations where the glyphs overlap. This may result in the pixel appearing too dark. To avoid this, the merging step combines the bitmaps for all the glyphs into a single texture. The filtering and blending steps are performed on the single texture rather than separately for each glyph. Thus, the merging steps combines the individual glyphs to achieve a continuous appearance and ensure there are not overlapping or separated glyphs.
The filtering step takes the merged glyphs and calculates the “coverage” for each pixel. The term coverage refers to determining the necessary intensity or value for each individual pixel used to display the merged glyphs. For example, a pixel that falls completely within the area of the glyph curve would have a 100% coverage. Likewise, a pixel that is completely outside the area of the glyph curve would have 0% coverage. Thus, the coverage value may fall anywhere in between 0% to 100% depending on the particular filtering method used for rendering the glyph.
The blending step may include sub-pixel rendering to improve the readability of the characters by exploiting the pixel structure of a Liquid Crystal Display (LCD). Specifically, sub-pixel rendering is possible because one pixel on an LCD screen is composed of three sub-pixels: one red, one green, and one blue (RGB). To the human eye these sub-pixels appear as one pixel. However, each of these pixels is unique and may be controlled individually. Thus, the resolution of the LCD screen may be improved by individually controlling the sub-pixels to increase the readability of text displayed on the LCD.
One method to render the text is to perform the first three steps on the CPU. That is, the rasterizing, merging, filtering steps are performed on the CPU and the blending step is preformed on the graphic processing unit (GPU). In terms of CPU usage, the merging and the filtering steps are the most computational intensive. To alleviate this usage, graphics device platform platforms such as Graphic Device Interface (GDI) or Windows Presentation Foundation (WPF) may be configured to cache the results of these operations. However, caching only helps so long as the cache contains the right data. For example, when text reflows or font size changes it becomes necessary to recalculate the filtered results. This requires the CPU to repeat the rendering process by performing the steps discussed above. In other words, the data stored in the cache is no longer useful and new values have to be calculated. Also, caching the results of filtering is less effective than caching the results of rasterization because it is per-run rather than per-glyph. In short, merging nearby glyphs and performing filtering on the merged glyphs is taxing on the CPU and has a detrimental effect on the performance of the computer.